
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Styx;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using UltimatePaladinHealerBT.Talents;
using Styx.TreeSharp;


using System.Reflection;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using System.IO;
using Styx.Common;
using Styx.Common.Helpers;
using Styx.CommonBot.POI;
using Styx.Helpers;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.WoWInternals.DBC;
using System.Drawing;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.Plugins;
using System.Dynamic;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

namespace UltimatePaladinHealerBT
{
    public partial class UltimatePalaHealerBT : CombatRoutine
    {
        public static UltimatePalaHealerBT Instance { get; private set; }
		//public static UltimatePalaHealerBT Instance = new UltimatePalaHealerBT();
        private WoWUnit lastCast = null;
        private WoWPlayer fallbacktank = null;
        private WoWPlayer tank;
        private WoWPlayer tank2;
        private WoWUnit Enemy;
        private Random rng;
        private WoWPlayer x;
        private WoWPlayer tar;
        private WoWPlayer mtank;
        private WoWUnit Epet;
        private WoWPlayer BlessTarget;
        private WoWPlayer RessTarget;
        private WoWPlayer CleanseTarget;
        private WoWPlayer UrgentCleanseTarget;
        private WoWPlayer UrgentHoFTarget;
        private WoWPlayer luatank;
        private WoWPlayer luatank2;
        private WoWPlayer focustank;
        private WoWPlayer focus;
        private WoWSpell ActualSpell;
        public List<string> GUIDlist;
        public string FormattedGUID;
        public ulong FinalGuid;

        private string lastBehaviour = null;
        private string actualBehaviour = null;
        private string usedBehaviour = null;
        private double maxAOEhealth = 85;
        private double dontHealAbove = 95;

        private string lastbless = null;
        private bool Global_chimaeron_p1 = false;
        private bool Global_chimaeron = false;
        private bool Global_SoD = false;
        private int Global_Judgment_range = 0; //for me..
        private bool Global_debug = true;
        private int Talent_last_word = 1;                      //0 1 or 2 point in the talent Last Word
        private bool _should_king;
        private string fallbacktankname;
        private string urgentdebuff;
        private int tryes;
        private bool specialhealing_warning=false;
        int i,j;
        private bool selective_resetted = false;
        public string[] NameorRM = new string[41];
        public string[] OrganizedNames = new string[41];
        public string[] WoWnames = new string[41];
        public int[] Raidsbugroup = new int[41];
        public int[] Raidorder = new int[41];
        public bool[] healornot = new bool[41];
        public int[] check_aoe = new int[41];
        public int SB1C;
        public int SB2C;
        public int SB3C;
        public int SB4C;
        public int SB5C;
        public int myclass;
        public static double allcasttaked=0;
        public static int how_many_cast=0;
        public static double max_allcasted = 0;
        public static double this_casted;
        public static double medium_time_to_decide;

        public WoWUnit CastingSpellTarget { get; set; }
        public string LastSpellCast { get; set; }
        public string LastSpell { get; set; }

        public WoWItem Trinket1;
        public WoWItem Trinket2;

        public Composite _combatBehavior;
        private Composite _pullBehavior;
        public Composite _restBehavior;
        public uint Latency { get { return StyxWoW.WoWClient.Latency; } }
        public override Composite CombatBehavior { get { return _combatBehavior; } }
        public override Composite CombatBuffBehavior { get { return _combatBehavior;/*_combatBuffsBehavior;*/ } }
        public override Composite HealBehavior { get { return _combatBehavior;/*_healBehavior;*/ } }
        public override Composite PreCombatBuffBehavior { get { return _combatBehavior;/*_preCombatBuffsBehavior;*/ } }
        public override Composite PullBehavior { get { return _pullBehavior; } }
        public override Composite PullBuffBehavior { get { return _combatBehavior;/*_pullBuffsBehavior*/ } }
        public override Composite RestBehavior { get { return _restBehavior; } }


        public string[] RaidNames = new string[41];
        public bool[] Raidrole = new bool[41];
        public int[] Subgroup = new int[41];

        public List<WoWPlayer> NearbyFriendlyPlayers { get { return ObjectManager.GetObjectsOfType<WoWPlayer>(true, true).Where(p => p.DistanceSqr <= 40 * 40 && p.IsFriendly).ToList(); } }
        public List<WoWPlayer> NearbyFarFriendlyPlayers { get { return ObjectManager.GetObjectsOfType<WoWPlayer>(true, true).Where(p => p.DistanceSqr <= 70 * 70 && p.IsFriendly && p.IsInMyPartyOrRaid).ToList(); } }
        public List<WoWPlayer> NearbyUnFriendlyPlayers { get { return ObjectManager.GetObjectsOfType<WoWPlayer>(false, false).Where(p => p.DistanceSqr <= 40 * 40 && !p.IsInMyPartyOrRaid && !p.IsDead).ToList(); } }
        
        public List<WoWUnit> NearbyUnfriendlyUnits
        {
            get
            {
                return
                    ObjectManager.GetObjectsOfType<WoWUnit>(false, false).Where(p => /*p.IsHostile && */!p.IsFriendly && !p.IsDead && /*!p.IsPet &&*/ p.DistanceSqr <= 40 * 40).
                        ToList();
            }
        }
        public List<WoWPlayer> PartyorRaid { get { if (Me.GroupInfo.IsInParty && !Me.GroupInfo.IsInRaid) { return Me.PartyMembers; } else if (Me.GroupInfo.IsInRaid) { return Me.RaidMembers; } else { return null; } } }
        
        private static Stopwatch sw = new Stopwatch();
        private static Stopwatch Trinket1_sw = new Stopwatch();
        private static Stopwatch Trinket2_sw = new Stopwatch();
        private static Stopwatch select_heal_watch = new Stopwatch();
        private static Stopwatch combatfrom = new Stopwatch();
        private static Stopwatch noncombatfrom = new Stopwatch();
        private static Stopwatch subgroupSW = new Stopwatch();
        private static Stopwatch performance = new Stopwatch();

        private string version = "2.0";
        private string revision = "265";

        public override sealed string Name
        {
            get
            {
                    return "UltimatePalaHealerBT v " + version + " revision " + revision;
            }
        }
		/*
        public static WoWContext TrainingDummyBehaviors { get; set; }
		public UltimatePalaHealerBT()
        {
            Instance = this;
            TrainingDummyBehaviors = WoWContext.Instances;
        }
		*/
        public override WoWClass Class
        {
            get
            {
                    return WoWClass.Paladin;
            }
        }

        public int setmyclass()
        {
			if (Me.Class == WoWClass.Paladin)
            {
                Global_debug=UPaHBTSetting.Instance.WriteLog;
                return 0;
            }
            else
            {
                slog("my class is {0}", Me.Class);
                return -1;
            }
        }
        private static LocalPlayer Me { get { return StyxWoW.Me; } }
        private readonly SpecManager Talent = new SpecManager();
        public override void Initialize()
        {
            tryes2 = 0;
            Instance = this;
            myclass = setmyclass();
            while (myclass < 0)
            {
                slog("Your class is not pala nor priest, insteas is {0} tryes {1} \n I'm retyng to undersand your class but if you are not a pala or priest you should not be here", Me.Class,tryes2);
                tryes2++;
                Thread.Sleep(1000);
                ObjectManager.Update();
            }
            if (myclass == 0)
            {
                slog(Color.Orange, "Hello Executor!\n I\'m UPaHCCBT and i\'m here to assist you keeping your friend alive\n You are using UPaHCCBT version {0} revision {1}", version, revision);
                slog("You are curently in {0}", Me.CurrentMap.Name);
                Global_Judgment_range = (int)SpellManager.Spells["Judgment"].MaxRange;
                slog(Color.Orange, "Your Judgment range is {0} yard! will use this value", Global_Judgment_range);
                _can_dispel_disease = true;
                _can_dispel_magic = true;
                _can_dispel_poison = true;
            }

            AttachEventHandlers();
            if (!CreateBehaviors())
            {
                return;
            }
        }

        public bool CreateBehaviors()
        {
            tryes = 0;
            while (Me==null || !Me.IsValid || Me.IsDead)
            {
                slog("i'm not valid, still on loading schreen {0}", tryes);
                tryes++;
                Thread.Sleep(1000);
                ObjectManager.Update();
            }
            if (!unitcheck(Me) && !Me.IsGhost)
            {
                if (unitcheck(StyxWoW.Me))
                {
                    slog("Me is not valid but OBJM.Me yes, we have a problem here..");
                }
                else
                {
                    slog("nor me nor OBJ.Me are valid, i shouldn't be here..");
                }
            }
            else if(!Me.IsGhost)
            {
                slog("All green! building behaviours now!");
            } else if (Me.IsGhost)
            {
                slog("So, i'm a Ghost, let's wait..");
            }
            Beahviour();
            tryes = 0;
            while (usedBehaviour == "WTF are you doing?")
            {
                tryes++;
                slog("No Valid Behaviour found, tryand again! that's try number {0}", tryes);
                if (unitcheck(Me))
                {
                    slog("party {0} raid {1} instance {2} pvpstatus {3} valid {4} behaviour {5}", Me.GroupInfo.IsInParty, Me.GroupInfo.IsInRaid, Me.IsInInstance, actualBehaviour, Me.IsValid, usedBehaviour);
                }
                else
                {
                    slog("i'm not valid, still on loading schreen and behaviour=WTF");
                }
                Thread.Sleep(1000);
                ObjectManager.Update();
                Beahviour();
            }
            slog(Color.HotPink, "{0}", usedBehaviour);
            if (myclass == 0)
            {
                UPaHBTSetting.Instance.Load();
                if (!selective_resetted) { UPaHBTSetting.Instance.Selective_Healing = false; selective_resetted = true; slog("Starting up, resetting selective healing to false"); }
                UPaHBTSetting.Instance.General_Stop_Healing = false;
                Load_Trinket();
                //Inizialize_Trinket();
                Variable_inizializer();
                _combatBehavior = Composite_Selector();
                _restBehavior = Composite_Rest_Selector();
                _pullBehavior = Composite_Pull_Selector();
                Variable_Printer();
                slog(Color.HotPink, "{0}", usedBehaviour);
                UPaHBTSetting.Instance.Save();
            }

            lastBehaviour = usedBehaviour;
            return true;
        }
        public override bool WantButton { get { return true; } }

        private Form _configForm;
        public override void OnButtonPress()
        {
            Inizialize_variable_for_GUI();
            if (usedBehaviour == "Raid" && _selective_healing) { BuildSubGroupArray(); }
            if (_configForm == null || _configForm.IsDisposed || _configForm.Disposing)
            {
                if (Me.Class == WoWClass.Paladin)
                {
                    _configForm = new UPaHCCBTConfigForm();
                }
            }
            if (_configForm != null)
            {
                try
                {
                    _configForm.ShowDialog();
                }
                catch(Exception e)
                {
                    slog(Color.Red,"Exception Thrown (Calling ConfigForm): {0}",e);
                }
            }
        }

    }
}
